package com.umeox.watch.moto.apiclient.http.request;


import com.umeox.watch.httpclient.core.constant.HttpMethod;
import com.umeox.watch.moto.apiclient.http.ApiEnum;

import java.io.File;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class WaasRequestBuilder {
    private ApiEnum api;
    private String host;
    private String accessToken;
    private Map<String, Object> paras;

    public WaasRequestBuilder() {
        this.paras = new HashMap<>();
    }

    public WaasRequestBuilder setApi(ApiEnum api) {
        this.api = api;
        return this;
    }

    public WaasRequestBuilder setHost(String host) {
        this.host = host;
        return this;
    }

    public WaasRequestBuilder setAccessToken(String accessToken) {
        this.accessToken = accessToken;
        return this;
    }

    public WaasRequestBuilder setParas(Map<String, Object> paras) {
        this.paras = paras;
        return this;
    }

    public WaasRequestBuilder addParam(String key, String value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequestBuilder addParam(String key, int value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequestBuilder addParam(String key, long value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequestBuilder addParam(String key, float value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequestBuilder addParam(String key, double value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequestBuilder addParam(String key, List value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequestBuilder addParam(String key, Map value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequestBuilder addParam(String key, File value) {
        this.paras.put(key, value);
        return this;
    }

    public WaasRequest build() {
        WaasRequestImpl request = new WaasRequestImpl();
        request.api = this.api;
        request.host = this.host;
        request.accessToken = this.accessToken;
        if (null == this.paras) {
            this.paras = new HashMap<>();
        }
        request.paras = this.paras;
        if (!isValid(this.paras)) {
            throw new IllegalArgumentException("params contains illegal value>>>");
        } else {
            return request;
        }
    }

    private boolean isValid(Map<String, Object> paras) {
        Iterator iterator = paras.entrySet().iterator();
        Map.Entry entry;
        do {
            if (!iterator.hasNext()) {
                return true;
            }
            entry = (Map.Entry) iterator.next();
        } while (isValid(entry.getValue()));
        return false;
    }

    private boolean isExists(File file) {
        return file != null && file.exists();
    }

    private boolean isValid(Object obj) {
        if (null == obj
                || obj instanceof Boolean
                || obj instanceof String
                || obj instanceof Integer
                || obj instanceof Long
                || obj instanceof Float
                || obj instanceof Double
                || obj instanceof BigDecimal
                || obj instanceof String[]) {
            return true;
        }else if (obj instanceof List) {
            return isValid((List) obj);
        } else if (obj instanceof Map) {
            return isValid((Map) obj);
        } else if (obj instanceof File) {
            return isExists((File) obj);
        } else {
            return false;
        }
    }

    private boolean isValid(List list) {
        Iterator it = list.iterator();
        Object obj;
        do {
            if (!it.hasNext()) {
                return true;
            }
            obj = it.next();
        } while (isValid(obj));
        return false;
    }

    static class WaasRequestImpl implements WaasRequest {
        private ApiEnum api;
        private String host;
        private String accessToken;
        private Map<String, Object> paras;

        @Override
        public ApiEnum getApi() {
            return api;
        }

        @Override
        public HttpMethod getMethod() {
            return api != null ? api.getMethod() : HttpMethod.GET;
        }

        @Override
        public String getHost() {
            return this.host;
        }

        @Override
        public String getPath() {
            return api != null ? api.getPath() : "";
        }

        @Override
        public String getToken() {
            return this.accessToken;
        }

        @Override
        public Map<String, Object> getParams() {
            return this.paras;
        }
    }
}
